#ifndef __DATABASE_JUDGE_H__
#define __DATABASE_JUDGE_H__

#include <string>
#include <mysql/mysql.h>
#include "../utility/configure.h"
#include "../utility/jsonObject.h"
#include "../utility/os.h"

const int SQL_MAX_SIZE = 1024;
const int DEFAULT_TIMEOUT = 5; //seconds

using std::string;

class DatabaseParams {
public:
    string host;
    int port;
    string root;
    string passwd;
    string user;
    string user_passwd;
    bool init_from_file(const string& file) {
        Configure conf(file);
        if (!conf.parse()) {
            return false;
        }
        std::unordered_map<std::string, std::string>& container = conf.groups["DATABASE_JUDGE"];
        host = container["MYSQL_HOST"];
        port = atoi(container["MYSQL_PORT"].c_str());
        root = container["MYSQL_ROOT_USER"];
        passwd = container["MYSQL_ROOT_PASSWD"];
        user = container["MYSQL_VISITOR_USER"];
        user_passwd = container["MYSQL_VISITOR_PASSWD"];
        return true;
    }
    void init(
                const string& host,
                int port,
                const string& root,
                const string& passwd,
                const string& user,
                const string& user_passwd) {
        this->host = host;
        this->port = port;
        this->root = root;
        this->passwd = passwd;
        this->user = user;
        this->user_passwd = user_passwd;
    }
};

extern DatabaseParams databaseParams;

// 创建一个mysql连接
ProcessStatus create_mysql_connect(MYSQL* conn, std::string host, int port,
                                    std::string user, std::string passwd, std::string database,
                                    int options = 0, int timeout = 5);

// 根据sql_file的最晚更新时间检查数据库是否需要更新
int check_update_database(MYSQL* conn, std::string database, std::string sql_file);

// 根据sql_file创建database数据库
ProcessStatus create_database(MYSQL *conn,
                              std::pair<std::string, std::string> user, // 普通用户权限的账号密码
                              std::string host, std::string database, std::string sql_file);

// 删除数据库
ProcessStatus drop_database(MYSQL *conn, const std::string& database);

// 选择数据库
ProcessStatus select_database(MYSQL* conn, std::string database);


// 在database中运行一句sql(select)命令
// return ProcessStatus
ProcessStatus run_single_select_sql(MYSQL* conn, std::string database, const std::string& sql, unsigned int timeLimit);

// 在database中运行一句sql(modify:update,delete,insert)命令
// return ProcessStatus
ProcessStatus run_single_modify_sql(MYSQL* conn, std::string database, const std::string& sql, unsigned int timeLimit);

// 获取最近一条命令的时间占用,返回值类型为pair<int,int>，若没有则返回-1
std::pair<int, int> get_last_statement_resource(MYSQL *conn);

// 将给定的mysql类型转为对应的JsonObjectPtr
JsonObjectPtr mysql_value_to_jsonobj(MYSQL_FIELD field, const char* value, int len);

// 将MYSQL_RES转为二维的列表，存储对象为JsonObjectPtr
JsonObjectPtr mysql_dump_result(MYSQL_RES* result);

// 运行一条sql语句
// 如果是select则返回查询结果,类型为JSONARRAY,表示查询到的数据
// 如果是update/delete/insert则返回类型为JSONINT,但结果为0
// 如果执行错误打印对应错误,返回类型为JSONINT,表示对应的错误码
JsonObjectPtr run_sql_result(MYSQL* conn, std::string database, const std::string& sql);

// 将对应json字符串的数据写入数据库用于测试
ProcessStatus write_example(MYSQL* conn, std::string database, const std::string& data);

#endif /* __DATABASE_JUDGE_H__ */
